package com.yan.crowd.controller;

import com.yan.crowd.api.MysqlRemoteService;
import com.yan.crowd.api.RedisApiService;
import com.yan.crowd.config.ShortMessageProperties;
import com.yan.crowd.constant.CrowdConstant;
import com.yan.crowd.entity.po.MemberPO;
import com.yan.crowd.entity.vo.MemberLoginVo;
import com.yan.crowd.entity.vo.MemberVo;
import com.yan.crowd.util.CrownUtil;
import com.yan.crowd.util.ResultEntity;
import org.bouncycastle.asn1.bc.ObjectDataSequence;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpSession;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

@Controller
public class MemberController {

    @Autowired
    private ShortMessageProperties shortMessageProperties;

    @Autowired
    private RedisApiService redisApiService;

    @Autowired
    private MysqlRemoteService mysqlRemoteService;

    /**
     * 注册操作->发送验证码请求
     *
     * @param phoneNum 接收验证码的手机号
     * @return success or failed
     */
    @ResponseBody
    @RequestMapping("auth/member/send/short/message")
    public ResultEntity<String> sendMessage(@RequestParam("phoneNum") String phoneNum) {

        ResultEntity<String> sendMessageResult = CrownUtil.sendCodeByShortMessage(
                shortMessageProperties.getHost(),
                shortMessageProperties.getPath(),
                shortMessageProperties.getAppCode(), phoneNum,
                shortMessageProperties.getSign(),
                shortMessageProperties.getSkin());
        if (ResultEntity.SUCCESS.equals(sendMessageResult.getResult())) {
            String code = sendMessageResult.getData();

            String key = CrowdConstant.REDIS_CODE_PREFIX + phoneNum;

            ResultEntity<String> saveCodeResultEntity = redisApiService.setRedisKeyValueWithTimeoutRemote(key, code, 15, TimeUnit.MINUTES);
            if (ResultEntity.SUCCESS.equals(saveCodeResultEntity.getResult())) {
                return ResultEntity.successWithoutData();
            } else {
                return saveCodeResultEntity;
            }
        } else {
            return sendMessageResult;
        }
    }

    @RequestMapping("/auth/do/member/register")
    public String register(MemberVo memberVo, Model model) {

        String phoneNum = memberVo.getPhoneNum();

        String key = CrowdConstant.REDIS_CODE_PREFIX + phoneNum;
        ResultEntity<String> redisKey = redisApiService.getRedisKey(key);

        String result = redisKey.getResult();

        if (ResultEntity.FAILED.equals(result)) {
            model.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, redisKey.getMessage());
            return "member-reg";
        }

        String redisCode = redisKey.getData();
        if (redisCode == null) {
            model.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.CODE_NOT_EXISTS);
            return "member-reg";
        }

        String code = memberVo.getCode();
        if (!Objects.equals(code, redisCode)) {
            model.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.CODE_INVALID);
            return "member-reg";
        }

        ResultEntity<String> removeEntity = redisApiService.deleteRedisKey(key);

        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        String userpswd = memberVo.getUserpswd();
        String encodePswd = bCryptPasswordEncoder.encode(userpswd);
        memberVo.setUserpswd(encodePswd);

        MemberPO memberPO = new MemberPO();
        BeanUtils.copyProperties(memberVo, memberPO);

        ResultEntity<MemberPO> memberPOResultEntity = mysqlRemoteService.saveMember(memberPO);

        if (ResultEntity.FAILED.equals(memberPOResultEntity.getResult())) {
            model.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, memberPOResultEntity.getMessage());
            return "member-reg";
        }

        return "redirect:/auth/member/to/login/page";
    }

    @RequestMapping("/auth/member/do/login")
    public String doLogin(@RequestParam("loginacct") String loginacct, @RequestParam("userpswd") String userpswd, Model model, HttpSession session) {
        ResultEntity<MemberPO> memberPOByLoginAcctRemote = mysqlRemoteService.getMemberPOByLoginAcctRemote(loginacct);
        if (ResultEntity.FAILED.equals(memberPOByLoginAcctRemote.getResult())) {
            model.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, memberPOByLoginAcctRemote.getMessage());
            return "member-login";
        }
        MemberPO memberPO = memberPOByLoginAcctRemote.getData();
        if (memberPO == null) {
            model.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_LOGIN_FAILED);
            return "member-login";
        }
        String password = memberPO.getUserpswd();
        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        boolean matchResult = bCryptPasswordEncoder.matches(userpswd, password);

        if (!matchResult) {
            model.addAttribute(CrowdConstant.ATTR_NAME_MESSAGE, CrowdConstant.MESSAGE_LOGIN_FAILED);
            return "member-login";
        }
        MemberLoginVo memberLoginVo = new MemberLoginVo(memberPO.getId(), memberPO.getUsername(), memberPO.getEmail());
        session.setAttribute("user", memberLoginVo);
        return "redirect:/auth/member/to/center/page";
    }

    @RequestMapping("/auth/member/logout")
    public String logout(HttpSession session){
        session.invalidate();
        return "redirect:/";
    }

}
